(function () {
"use strict";
var cfg = window.VSL_CONFIG;
if (!cfg) {
console.error("[VSL] Config não carregado (vsl-config.php ou config.js).");
return;
}
var analytics = window.VSL_ANALYTICS || null;
var sentMilestones = {};
var sessionId = (function () {
var key = "kks_vsl_session";
try {
var id = localStorage.getItem(key);
if (!id) {
id = "sess_" + Math.random().toString(36).slice(2) + Date.now().toString(36);
localStorage.setItem(key, id);
}
return id;
} catch (e) {
return "sess_" + Date.now();
}
})();
function parseUtms() {
var params = new URLSearchParams(window.location.search);
return {
utm_source: params.get("utm_source") || "",
utm_medium: params.get("utm_medium") || "",
utm_campaign: params.get("utm_campaign") || "",
utm_content: params.get("utm_content") || "",
utm_term: params.get("utm_term") || "",
fbclid: params.get("fbclid") || "",
gclid: params.get("gclid") || "",
ttclid: params.get("ttclid") || "",
};
}
var utms = parseUtms();
function track(eventName, extra) {
if (!analytics || !analytics.events_url) return;
var payload = {
embed_id: analytics.embed_id,
video_id: analytics.video_id,
project_id: analytics.project_id,
event_name: eventName,
session_id: sessionId,
current_time: video ? video.currentTime : 0,
duration: video && video.duration ? video.duration : 0,
percent: 0,
url: window.location.href,
referrer: document.referrer || "",
user_agent: navigator.userAgent || "",
};
Object.assign(payload, utms);
if (extra) Object.assign(payload, extra);
if (payload.duration > 0) {
payload.percent = Math.min(100, (payload.current_time / payload.duration) * 100);
}
var body = JSON.stringify(payload);
try {
if (navigator.sendBeacon) {
navigator.sendBeacon(
analytics.events_url,
new Blob([body], { type: "text/plain;charset=UTF-8" })
);
return;
}
} catch (e) {}
fetch(analytics.events_url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: body,
keepalive: true,
credentials: "omit",
mode: "cors",
}).catch(function () {});
}
var container = document.getElementById(cfg.containerId || "vsl-player");
if (!container) {
console.error("[VSL] Container não encontrado:", cfg.containerId);
return;
}
var layout = cfg.layout || {};
var loadingCfg = cfg.loading || {};
var overlayCfg = cfg.overlay || {};
var progressCfg = cfg.progressBar || {};
var videoCfg = cfg.video || {};
container.className = "vsl-player";
container.classList.remove("kks-embed-loading");
container.style.minHeight = "";
container.style.background = "";
container.innerHTML =
'
' +
'
' +
'
' +
'
' +
'
' + (loadingCfg.startPercent || 50) + '%
' +
'
' +
'
' +
'
' +
'
' +
'
';
var wrapper = container.querySelector(".vsl-wrapper");
var video = container.querySelector(".vsl-video");
var loading = container.querySelector(".vsl-loading");
var percentEl = container.querySelector(".vsl-percent");
var overlay = container.querySelector(".vsl-overlay");
var progress = container.querySelector(".vsl-fake-progress");
var spinner = container.querySelector(".vsl-spinner");
var fakeBar = container.querySelector(".vsl-fake-bar");
var tapBtn = container.querySelector(".vsl-tap-btn");
wrapper.style.aspectRatio = layout.aspectRatio || "16 / 9";
wrapper.style.background = layout.background || "#000";
wrapper.style.borderRadius = layout.borderRadius || "0";
if (layout.maxWidth) {
container.style.maxWidth = layout.maxWidth;
container.style.width = "100%";
container.style.marginLeft = "auto";
container.style.marginRight = "auto";
}
if (overlayCfg.background) {
overlay.style.setProperty("--vsl-overlay-bg", overlayCfg.background);
overlay.style.background = overlayCfg.background;
}
if (overlayCfg.borderColor) {
overlay.style.setProperty("--vsl-overlay-border", overlayCfg.borderColor);
overlay.style.borderColor = overlayCfg.borderColor;
}
if (loadingCfg.spinnerColor && spinner) {
spinner.style.borderTopColor = loadingCfg.spinnerColor;
}
var barHeight = progressCfg.heightPx || 10;
fakeBar.style.height = barHeight + "px";
fakeBar.style.background = progressCfg.trackColor || "rgba(255,255,255,0.2)";
progress.style.background = progressCfg.color || "#3D85C6";
var percent = loadingCfg.startPercent || 50;
var maxPercent = loadingCfg.maxPercent || 99;
var hlsInstance = null;
var autoplayStarted = false;
track("page_view");
var fakeLoad = setInterval(function () {
if (percent < maxPercent) {
percent++;
percentEl.textContent = percent + "%";
}
}, loadingCfg.tickIntervalMs || 35);
function hideLoading() {
loading.style.display = "none";
clearInterval(fakeLoad);
}
function showOverlay() {
hideLoading();
overlay.style.display = "flex";
}
async function tryMutedAutoplay() {
if (autoplayStarted) return;
autoplayStarted = true;
video.muted = videoCfg.mutedOnAutoplay !== false;
video.playsInline = videoCfg.playsinline !== false;
video.controls = false;
try {
await video.play();
track("video_play");
showOverlay();
} catch (e) {
showOverlay();
}
}
var fallbackTimer = setTimeout(showOverlay, loadingCfg.fallbackMs || 3000);
function playerReady() {
clearTimeout(fallbackTimer);
track("video_loaded");
tryMutedAutoplay();
}
function setupHls() {
if (window.Hls && Hls.isSupported()) {
hlsInstance = new Hls(cfg.hls || {});
hlsInstance.loadSource(cfg.streamUrl);
hlsInstance.attachMedia(video);
hlsInstance.on(Hls.Events.MANIFEST_PARSED, function () {
playerReady();
});
hlsInstance.on(Hls.Events.ERROR, function (event, data) {
console.warn("[VSL] Erro HLS:", data);
if (data && data.fatal) {
switch (data.type) {
case Hls.ErrorTypes.NETWORK_ERROR:
hlsInstance.startLoad();
break;
case Hls.ErrorTypes.MEDIA_ERROR:
hlsInstance.recoverMediaError();
break;
default:
hlsInstance.destroy();
track("video_error");
showOverlay();
break;
}
}
});
return;
}
if (video.canPlayType("application/vnd.apple.mpegurl")) {
video.src = cfg.streamUrl;
video.addEventListener("loadedmetadata", playerReady, { once: true });
video.load();
return;
}
console.error("[VSL] Este navegador não suporta HLS.");
track("video_error");
showOverlay();
}
setupHls();
// Fluxo VTurb: 1º toque mostra ícone; 2º pausa; some em ~3s se não confirmar
var allowTogglePause = false;
var tapHideTimer = null;
var TAP_HIDE_MS = 3000;
function clearTapHideTimer() {
if (tapHideTimer) {
clearTimeout(tapHideTimer);
tapHideTimer = null;
}
}
function hideTapBtn() {
clearTapHideTimer();
tapBtn.hidden = true;
tapBtn.classList.remove("is-paused", "is-armed");
}
function showTapBtn(mode) {
clearTapHideTimer();
tapBtn.hidden = false;
tapBtn.classList.toggle("is-paused", mode === "paused");
tapBtn.classList.toggle("is-armed", mode === "armed");
tapBtn.setAttribute("aria-label", mode === "paused" ? "Reproduzir" : "Pausar");
if (mode === "armed") {
tapHideTimer = setTimeout(function () {
if (!video.paused) hideTapBtn();
}, TAP_HIDE_MS);
}
}
overlay.addEventListener("click", async function () {
overlay.style.display = "none";
hideLoading();
allowTogglePause = true;
hideTapBtn();
video.muted = false;
video.controls = false;
if (videoCfg.restartOnUnmute) {
try {
video.currentTime = 0;
} catch (e) {}
}
track("video_unmute_click");
try {
await video.play();
} catch (e) {
if (videoCfg.showNativeControlsOnFallback !== false) {
video.controls = true;
}
video.muted = false;
video.play().catch(function () {});
}
});
tapBtn.addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
if (!allowTogglePause || video.controls) return;
if (video.paused) {
video.play().catch(function () {});
hideTapBtn();
return;
}
// 2º toque no ícone armado → pausa
if (tapBtn.classList.contains("is-armed")) {
video.pause();
showTapBtn("paused");
return;
}
showTapBtn("armed");
});
wrapper.addEventListener("click", function (e) {
if (!allowTogglePause) return;
if (e.target.closest(".vsl-overlay")) return;
if (e.target.closest(".vsl-tap-btn")) return;
if (video.controls) return;
e.preventDefault();
if (video.paused) {
video.play().catch(function () {});
hideTapBtn();
return;
}
// Já armado: 2º toque em qualquer lugar do vídeo também pausa
if (tapBtn.classList.contains("is-armed") && !tapBtn.hidden) {
video.pause();
showTapBtn("paused");
return;
}
// 1º toque: só mostra o ícone (evita miss-click)
showTapBtn("armed");
});
video.addEventListener("play", function () {
if (allowTogglePause && !tapBtn.classList.contains("is-armed")) {
hideTapBtn();
}
});
video.addEventListener("pause", function () {
if (!allowTogglePause || video.controls) return;
if (video.ended) {
hideTapBtn();
return;
}
showTapBtn("paused");
});
video.addEventListener("playing", hideLoading);
video.addEventListener("timeupdate", function () {
if (video.duration && isFinite(video.duration) && progress) {
var pct = (video.currentTime / video.duration) * 100;
progress.style.width = pct + "%";
[25, 50, 75, 100].forEach(function (m) {
if (pct >= m && !sentMilestones[m]) {
sentMilestones[m] = true;
track("video_" + m);
}
});
}
});
video.addEventListener("pause", function () {
track("video_pause");
});
video.addEventListener("ended", function () {
if (progress) progress.style.width = "100%";
track("video_100");
});
document.addEventListener("click", function (e) {
var cta = e.target.closest("[data-vsl-cta]");
if (cta && analytics && analytics.events_url) {
track("cta_click");
}
});
})();